#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>

int main (int argc, char **argv) {

   if (argc != 2) {
      printf("Usage: ./mm <data_file>\n");
      exit(-1);
   }

   int i,j,k;  /* Counters */

   int **A,    /* First  matrix */
       **B,    /* Second matrix */ 
       **C;    /* Result matrix */

   int dim1,   /* Rows of first matrix                         */
       dim2,   /* Cols of first matrix = Rows of second matrix */
       dim3;   /* Cols of second matrix                        */

   struct timeval t1,
                  t2;

   double start,
          end,
          diff;

   if (access(argv[1], R_OK) != 0) {
      printf ("Error ocurred when trying to read '%s'\n", argv[1]);
      exit(-1);
   }

   FILE *input = fopen (argv[1], "r");

   /* Read dimensions of matrix's */
   fscanf(input, "%d\n", &dim1);
   fscanf(input, "%d\n", &dim2);
   fscanf(input, "%d\n", &dim3);

   /* Show dimensions */
   printf("Filas primera matriz: %d\n", dim1);
   printf("Filas segunda matriz: %d\n", dim2);
   printf("Columnas segunda matriz: %d\n", dim3);
   
   /* Allocate memory for matrix */
   A = (int **) malloc (dim1 * sizeof(int *));
   B = (int **) malloc (dim2 * sizeof(int *));
   C = (int **) malloc (dim1 * sizeof(int *));

   /* Read first matrix */
   for (i = 0; i < dim1; i++) {
      A[i] = (int *) malloc(dim2 * sizeof(int));
      C[i] = (int *) malloc(dim3 * sizeof(int));
      for (j = 0; j < dim2; j++)
         fscanf(input, "%d", &A[i][j]);
   }

   /* Read second matrix */
   for (i = 0; i < dim2; i++) {
      B[i] = (int *) malloc(dim3 * sizeof(int));
      for (j = 0; j < dim3; j++)
         fscanf(input, "%d", &B[i][j]);
   }
   
   /* Close file descriptor */
   fclose(input);

   /* Save the start of interval */
   gettimeofday(&t1, NULL);

   /* Calculate matrix product */
   for (i = 0; i < dim1; i++) {
      for (j = 0; j < dim3; j++) {
         C[i][j] = 0;
         for (k = 0; k < dim2; k++)
            C[i][j] += A[i][k] * B[k][j];
      }
   }

   /* Save the end of interval */
   gettimeofday(&t2, NULL);

   /* Calculate process duration */
   start = (double)(t1.tv_sec * 1.0e6) + (double)t1.tv_usec;
   end   = (double)(t2.tv_sec * 1.0e6) + (double)t2.tv_usec;
   diff  = (end - start) / 1.0e6;

   /* Show process time */
   printf ("Time of product: %f\n", diff);

   /* Show matrix's and result */
   /*
   printf("\nMatriz A:\n");
   for (i = 0; i < dim1; i++) {
      for (j = 0; j < dim2; j++)
         printf ("%d ", A[i][j]);
      printf("\n");
   }

   printf("\nMatriz B:\n");
   for (i = 0; i < dim2; i++) {
      for (j = 0; j < dim3; j++)
         printf ("%d ", B[i][j]);
      printf("\n");
   }
*/

   printf("\nResult: ");
/*   for (i = 0; i < dim1; i++)
      for (j = 0; j < dim3; j++)
         printf ("%d ", C[i][j]);
   printf("\n");*/
   printf("%d\n", C[0][0]);
   
   return 0;
}
